<?php

/**
 * Description of ProjectInfo
 *
 * @author     Mon Zafra <monzee at gmail>
 * @copyright  (c)2009 Mon Zafra
 * @category   Mz
 * @package
 * @license    http://mz-project.googlecode.com/svn/trunk/LICENSE   MIT License
 * @version    SVN: $Id: ProjectInfo.php 53 2009-12-06 23:47:39Z monzee@gmail.com $
 */
class Acl_Service_ProjectInfo
{
    /**
     *
     * @var Zend_Controller_Front
     */
    protected $_front;

    public function __construct($front)
    {
        $this->_front = $front;
    }

    public function getActions($controller = null, $module = null)
    {
        if (null !== $controller && null === $module) {
            $module = $this->_front->getDefaultModule();
        }
        $controllers = $this->getControllers($module, true);
        $actions = array();
        foreach ($controllers as $moduleName => $specs) {
            $actions[$moduleName] = array();
            $controllerActions = array();
            foreach ($specs as $spec) {
                $filename = $spec['filename'];
                $controllerName = $spec['controller'];
                if (null !== $controller && $controllerName != $controller) {
                    continue;
                }
                $controllerClass = $this->_filenameToControllerClass($filename, $moduleName);
                if (!class_exists($controllerClass, false)) {
                    include $filename;
                }
                try {
                    $c = new ReflectionClass($controllerClass);
                    $controllerActions[$controllerName] = $this->_getControllerActions($c);
                } catch (ReflectionException $e) {
                    continue;
                }
            }
            if (null !== $controller) {
                return isset($controllerActions[$controller]) ? $controllerActions[$controller]
                    : array();
            }
            if (null !== $module) {
                return $controllerActions;
            }
            $actions[$moduleName] = $controllerActions;
        }
        return $actions;
    }

    public function getControllers($module = null, $includeFilename = false)
    {
        $controllers = array();
        $front = $this->_front;
        $controllerDirs = null === $module ? $front->getControllerDirectory()
                : array($module => $front->getControllerDirectory($module));
        foreach ($controllerDirs as $module => $dir) {
            if (empty($dir)) {
                continue;
            }
            $directory = new DirectoryIterator($dir);
            $controllers[$module] = array();
            foreach ($directory as $file) {
                $filename = $file->getFilename();
                if ('controller.php' == strtolower(substr($filename, -strlen('controller.php')))) {
                    $controller = $this->_filenameToController($filename);
                    if (!$includeFilename) {
                        $controllers[$module][] = $controller;
                    } else {
                        $controllers[$module][] = array(
                            'controller' => $controller,
                            'filename' => $dir . '/' . $filename,
                        );
                    }
                }
            }
        }
        return $controllers;
    }

    public function getModules()
    {
        return array_keys($this->_front->getControllerDirectory());
    }

    protected function _filenameToController($file)
    {
        $controller = substr($file, 0, -strlen('controller.php'));
        return $this->_camelToLowerDashed($controller);
    }

    protected function _filenameToControllerClass($filename, $module)
    {
        $class = '';
        if ($module != $this->_front->getDefaultModule()
                || $this->_front->getParam('prefixDefaultModule')) {
            $class = ucfirst($module) . '_';
        }
        return $class . pathinfo($filename, PATHINFO_FILENAME);
    }

    protected function _getControllerActions(ReflectionClass $controller)
    {
        $publicMethods = $controller->getMethods(ReflectionMethod::IS_PUBLIC);
        $actions = array();
        foreach ($publicMethods as &$method) {
            $name = $method->getName();
            if ('Action' == substr($name, -6)) {
                $actions[] = $this->_camelToLowerDashed(substr($name, 0, -6));
            }
        }
        return $actions;
    }

    protected function _camelToLowerDashed($string)
    {
        return strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '-$1', $string));
    }


}